using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Reflection;
using System.Web;
using Microsoft.Office.Core;

namespace PengYouClient
{
    public partial class PublishAs : Form
    {
        delegate void DelegateIncrementProgressBar();
        delegate void DelegateDrawFileList();
        delegate void DelegateRemoveProgressBar();
        delegate void DelegateCreateProgressBar();
        delegate void DelegateInhibControl_Off();
        delegate void DelegateInhibControl_On();
        DelegateIncrementProgressBar m_DelegateIncrementProgressBar;
        DelegateDrawFileList m_DelegateDrawFileList;
        DelegateRemoveProgressBar m_DelegateRemoveProgressBar;
        DelegateCreateProgressBar m_DelegateCreateProgressBar;
        DelegateInhibControl_Off m_DelegateInhibControl_Off;
        DelegateInhibControl_On m_DelegateInhibControl_On;

        public DavContext context;
        ArrayList directory_listing;
        SortDirection direction;
        string CurrentDir;
        int ComboIndex = 0;
        public bool getlisting;
        bool ProgressBarExists = false;

        bool getDirectoryListing_success;
        string error_reason;

        string originalDocName;
        string originalDocPath;
        bool isPengYouDoc;

        Thread FillThread;
        Thread ProgressBarThread;

        Word._Application app;
        Connect connect;

        bool moreInfo_developed = false;

        string basedir = SettingsManager.Server_host + ":" + SettingsManager.Server_port + SettingsManager.Ressource_basedir;

        public PublishAs(object app, Connect connect)
        {
            m_DelegateIncrementProgressBar = new DelegateIncrementProgressBar(this.IncrementProgressBar);
            m_DelegateDrawFileList = new DelegateDrawFileList(this.DrawFileList);
            m_DelegateRemoveProgressBar = new DelegateRemoveProgressBar(this.RemoveProgressBar);
            m_DelegateCreateProgressBar = new DelegateCreateProgressBar(this.CreateProgressBar);
            m_DelegateInhibControl_Off = new DelegateInhibControl_Off(this.InhibControls_Off);
            m_DelegateInhibControl_On = new DelegateInhibControl_On(this.InhibControls_On);

            this.app = (Word._Application)app;
            this.connect = connect;

            InitializeComponent();
        }

        public void CreateProgressBar()
        {
            this.GetDavState = new System.Windows.Forms.ProgressBar();
            this.Controls.Add(this.GetDavState);

            this.GetDavState.Location = new System.Drawing.Point(93, 290);
            this.GetDavState.Name = "GetDavState";
            this.GetDavState.Size = new System.Drawing.Size(347, 23);
            this.GetDavState.TabIndex = 8;
            this.ProgressBarExists = true;
        }

        public void IncrementProgressBar()
        {
            this.GetDavState.Increment(1);
        }

        public void RemoveProgressBar()
        {
            if (this.ProgressBarExists == true)
                this.GetDavState.Visible = false;
        }

        private void InhibControls_On()
        {
            this.MoreInfoButton.Enabled = false;
            this.PublishHereButton.Enabled = false;
            this.PathListCombo.Enabled = false;
            this.FileList.Enabled = false;
            this.UpButton.Enabled = false;
        }

        private void InhibControls_Off()
        {
            this.MoreInfoButton.Enabled = true;
            this.PublishHereButton.Enabled = true;
            this.PathListCombo.Enabled = true;
            this.FileList.Enabled = true;
            this.UpButton.Enabled = true;
        }

        public class FillFileListThread
        {
            PublishAs pa;

            public FillFileListThread(PublishAs pa)
            {
                this.pa = pa;
            }

            public void FillThreadRun()
            {
                pa.getlisting = false;
                pa.FillFileList(pa.CurrentDir);
                pa.getlisting = true;
                pa.Invoke(pa.m_DelegateDrawFileList);
            }
        }

        public class IncrementProgressBarThread
        {
            PublishAs pa;

            public IncrementProgressBarThread(PublishAs pa)
            {
                this.pa = pa;
            }

            public void IncrementProgressBarThreadRun()
            {
                Thread.Sleep(500);
                if (pa.getlisting == false)
                {
                    pa.Invoke(pa.m_DelegateInhibControl_On);
                    pa.Invoke(pa.m_DelegateCreateProgressBar);
                }
                while (pa.getlisting == false)
                {
                    Thread.Sleep(500);
                    pa.Invoke(pa.m_DelegateIncrementProgressBar);                    
                }
                pa.Invoke(pa.m_DelegateRemoveProgressBar);
                pa.Invoke(pa.m_DelegateInhibControl_Off);
            }
        }

        private void DrawComboPwd(string pwd)
        {
            this.PathListCombo.Items.Add(pwd);
            this.PathListCombo.SelectedIndex = this.ComboIndex;
            this.ComboIndex++;
        }

        public enum SortDirection
        {
            Ascending,
            Descending
        }

        public class FileComparer : IComparer
        {
            private SortDirection m_direction = SortDirection.Ascending;

            public FileComparer() : base() { }

            public FileComparer(SortDirection direction)
            {
                this.m_direction = direction;
            }

            int IComparer.Compare(object a, object b)
            {
                Hashtable x = (Hashtable)a;
                Hashtable y = (Hashtable)b;

                if (m_direction == SortDirection.Ascending)
                {
                    if (((bool)x["is_dir"]) == true && ((bool)y["is_dir"]) == false)
                        return -1;
                    if (((bool)x["is_dir"]) == false && ((bool)y["is_dir"]) == true)
                        return 0;
                }
                else
                {
                    if (((bool)x["is_dir"]) == true && ((bool)y["is_dir"]) == false)
                        return 0;
                    if (((bool)x["is_dir"]) == false && ((bool)y["is_dir"]) == true)
                        return -1;
                }
                return (((string)x["name"]).CompareTo((string)y["name"]));
            }
        }

        private void FillFileList_LaunchThread()
        {
            FillFileListThread h_fill_th = new FillFileListThread(this);
            this.FillThread = new Thread(new ThreadStart(h_fill_th.FillThreadRun));
            FillThread.Start();
        }

        private void FillFileList(string ressource)
        {
            bool success;

            DavRessource Dav = new DavRessource(ressource, this.context);
            success = Dav.GetDirectoryListing(out this.directory_listing);
            this.direction = SortDirection.Ascending;

            this.error_reason = Dav.ResultReason;
            this.getDirectoryListing_success = success;

            DavRessource pengYouDoc = new DavRessource(this.basedir + this.originalDocPath + this.originalDocName, this.context);
            bool pengyouDocExists = pengYouDoc.FileExists();
            if (!pengyouDocExists)
                this.isPengYouDoc = false;
        }

        private void IncrementProgressBar_LaunchThread()
        {
            IncrementProgressBarThread h_progress_th = new IncrementProgressBarThread(this);
            this.ProgressBarThread = new Thread(new ThreadStart(h_progress_th.IncrementProgressBarThreadRun));
            this.ProgressBarThread.Start();
        }

        private void LaunchErrorWindow()
        {
            string caption = LanguageManager.GetString("WindowPublishAsConnectionError");
            MessageBoxButtons buttons = MessageBoxButtons.OK;
            DialogResult result;

            result = MessageBox.Show(this, this.error_reason, caption, buttons);
            if (result == DialogResult.OK)
            {
                this.ProgressBarThread.Abort();
                this.FillThread.Abort();
                this.Close();
            }
        }

        private void DrawFileList()
        {
            if (getDirectoryListing_success == false)
                LaunchErrorWindow();
            this.FileList.Items.Clear();
            this.directory_listing.Sort(new FileComparer(this.direction));
            IEnumerator DicEnum = this.directory_listing.GetEnumerator();
            while (DicEnum.MoveNext())
            {
                int image;
                DateDiff lastmodified = new DateDiff(DateTime.Now, (DateTime)((Hashtable)DicEnum.Current)["last_modified"]);
                if (((bool)((Hashtable)DicEnum.Current)["is_dir"]) == true)
                {
                    lastmodified.Diff = "";
                    image = 0;
                }
                else
                    image = 1;

                System.Windows.Forms.ListViewItem Ligne = new System.Windows.Forms.ListViewItem(new string[] {
                HttpUtility.UrlDecode(((Hashtable)DicEnum.Current)["name"].ToString()),
                HttpUtility.UrlDecode(((Hashtable)DicEnum.Current)["last_author"].ToString()),
                ((Hashtable)DicEnum.Current)["creation_date"].ToString(),
                lastmodified.Diff,
                ((Hashtable)DicEnum.Current)["comment"].ToString()}, image);

                this.FileList.Items.Add(Ligne);
            }
        }

        private void stopThreadClose()
        {
            if (this.ProgressBarThread != null)
                this.ProgressBarThread.Abort();
            if (this.FillThread != null)
                this.FillThread.Abort();
            this.Close();
        }

        private void CancelButton_Click(object sender, EventArgs e)
        {
            stopThreadClose();
        }

        private void UpButton_MouseEnter(object sender, EventArgs e)
        {
            this.UpButton.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
        }

        private void UpButton_MouseLeave(object sender, EventArgs e)
        {
            this.UpButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
        }

        private void FileList_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            if (this.direction == SortDirection.Ascending)
                this.direction = SortDirection.Descending;
            else
                this.direction = SortDirection.Ascending;            
            DrawFileList();
        }

        private void FileList_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            int item_index = ((ListView)sender).FocusedItem.Index;
            Hashtable item = ((Hashtable)this.directory_listing[item_index]);

            if (((bool)item["is_dir"]) == true)
            {
                this.CurrentDir = item["ressource_name"].ToString();
                DrawComboPwd(CurrentDir);
                FillFileList_LaunchThread();
                IncrementProgressBar_LaunchThread();
            }
        }

        private void UpButton_MouseClick(object sender, MouseEventArgs e)
        {
            if (this.CurrentDir.CompareTo(this.basedir) != 0)
            {
                if (this.CurrentDir.EndsWith("/"))
                    this.CurrentDir = this.CurrentDir.Remove(this.CurrentDir.LastIndexOf("/"));
                this.CurrentDir = this.CurrentDir.Remove(this.CurrentDir.LastIndexOf("/") + 1);
                if (this.CurrentDir.EndsWith("/"))
                    this.CurrentDir = this.CurrentDir.Remove(this.CurrentDir.LastIndexOf("/"));

                DrawComboPwd(this.CurrentDir);
                FillFileList_LaunchThread();
                IncrementProgressBar_LaunchThread();
            }
        }

        private void PathListCombo_SelectionChangeCommitted(object sender, EventArgs e)
        {
            string ItemMsg;

            ItemMsg = ((ComboBox)sender).SelectedItem.ToString();
            if (ItemMsg.CompareTo(this.CurrentDir) != 0)
            {
                this.CurrentDir = ItemMsg;
                FillFileList_LaunchThread();
                IncrementProgressBar_LaunchThread();
            }
        }

        private bool CheckDocumentPath()
        {
            bool result_return = true;
            string path = app.ActiveDocument.Path;
            if (path.CompareTo("") == 0)
            {
                try
                {
                    moreInfo_developed = true;
                    return true;
                }
                catch (Exception)
                {
                    stopThreadClose();
                    result_return = false;
                }
            }
            return result_return;
        }

        private bool UpdateCustomDocumentPropertie(string propName, string propValue, Word.Document doc)
        {
            try
            {
                object docProps = doc.CustomDocumentProperties;
                Type docPropsType = docProps.GetType();
                object Prop = docPropsType.InvokeMember("Item",
                    BindingFlags.Default |
                    BindingFlags.GetProperty,
                    null, docProps,
                    new object[] { propName });
                Type PropType = Prop.GetType();
                PropType.InvokeMember("Item",
                    BindingFlags.Default |
                    BindingFlags.SetProperty,
                    null, docProps,
                    new object[] { propName, propValue });
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        private bool SetCustomDocumentPropertie(string strIndex, string strValue, Word.Document doc)
        {
            DocumentProperties prop;
            object omissing = System.Reflection.Missing.Value;

            try
            {
                prop = (DocumentProperties)doc.CustomDocumentProperties;
                prop.Add(strIndex, false, Microsoft.Office.Core
                    .MsoDocProperties.msoPropertyTypeString, strValue, omissing);
                return true;
            }
            catch (Exception)
            {
                if (!UpdateCustomDocumentPropertie(strIndex, strValue, doc))
                    return false;
                else
                    return true;
            }
        }

        private void SetWordDocumentProperties(Word.Document doc)
        {
            bool success = true;

            string docbasedir = this.CurrentDir.Substring(this.basedir.Length, this.CurrentDir.Length - this.basedir.Length);
            if (!SetCustomDocumentPropertie("PengYou", "Oui", doc))
                success = false;
            if (!SetCustomDocumentPropertie("PengYouBaseDir", docbasedir, doc))
                success = false;
            if (!SetCustomDocumentPropertie("PengYouDocName", app.ActiveDocument.Name, doc))
                success = false;
            if (success == false)
                System.Windows.Forms.MessageBox.Show(LanguageManager.GetString("WindowPublishAsSetPropertiesError"));
            doc.Save();            
        }

        private void SetText()
        {
            this.Text = LanguageManager.GetString("WindowPublishAs");
            CancelButton.Text = LanguageManager.GetString("WindowPublishAsCancelButton");
            DFile.Text = LanguageManager.GetString("WindowPublishAsListFile");
            DCreationDate.Text = LanguageManager.GetString("WindowPublishAsListCreationDate");
            DLastAuthor.Text = LanguageManager.GetString("WindowPublishAsListLastAuthor");
            DLastEdition.Text = LanguageManager.GetString("WindowPublishAsListLastEdition");
            MoreInfoButton.Text = LanguageManager.GetString("WindowPublishAsMoreInfoButton");
            DDescription.Text = LanguageManager.GetString("WindowPublishAsListDescription");
            PublishHereButton.Text = LanguageManager.GetString("WindowPublishAsPublishButton");
        }

        private void PublishAs_Load(object sender, EventArgs e)
        {
            if (pengyouUtils.GetWordDocumentProp(app, "PengYouDocName", out originalDocName))
            {
                pengyouUtils.GetWordDocumentProp(app, "PengYouBaseDir", out originalDocPath);
                this.isPengYouDoc = true;                
                this.docnameBox.Text = originalDocName;
            }
            else
                this.isPengYouDoc = false;
            SetText();
            if (CheckDocumentPath() != false)
            {
                DrawComboPwd(basedir);
                this.context = new DavContext(SettingsManager.Server_host, Convert.ToInt32(SettingsManager.Server_port),
        SettingsManager.Server_user, SettingsManager.Server_pass);
                this.CurrentDir = basedir;
                if (!this.app.ActiveDocument.Name.EndsWith(".doc"))
                    this.docnameBox.Text = this.app.ActiveDocument.Name + ".doc";

                FillFileList_LaunchThread();
                IncrementProgressBar_LaunchThread();
            }
        }

        private void PublishAs_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (this.ProgressBarThread != null)
                this.ProgressBarThread.Abort();
            if (this.FillThread != null)
                this.FillThread.Abort();
        }

        private void MoreInfoButton_Click(object sender, EventArgs e)
        {
            if (moreInfo_developed == false)
            {
                Size s = new Size(620, 455);
                this.Size = s;
                this.Refresh();
                moreInfo_developed = true;
            }
            else
            {
                Size s = new Size(620, 345);
                this.Size = s;
                this.Refresh();
                moreInfo_developed = false;
            }
        }

        private void PublishHereButton_Click(object sender, EventArgs e)
        {
            string path = app.ActiveDocument.Path;
            string docbasedir = this.CurrentDir.Substring(this.basedir.Length, this.CurrentDir.Length - this.basedir.Length);
            object omissing = Missing.Value;
            bool nameChanged = false;

            if (path.CompareTo("") == 0)
            {
                if (!docbasedir.EndsWith("/"))
                    docbasedir += "/";
                object filename = SettingsManager.PengYouPath + "repository\\" + docbasedir + this.docnameBox.Text;
                app.ActiveDocument.SaveAs(ref filename, ref omissing, ref omissing, ref omissing, ref omissing, ref omissing,
                    ref omissing, ref omissing, ref omissing, ref omissing, ref omissing, ref omissing,
                    ref omissing, ref omissing, ref omissing, ref omissing);
            }
            else
                app.ActiveDocument.Save();
            Publish pub;
            if (this.isPengYouDoc == true && this.originalDocName == this.docnameBox.Text)
                pub = new Publish(app, this.CurrentDir, "publishascomment");
            else if (this.isPengYouDoc == true && this.originalDocName != this.docnameBox.Text)
            {
                nameChanged = true;
                if (!this.CurrentDir.EndsWith("/"))
                    this.CurrentDir += "/";
                pub = new Publish(app, this.CurrentDir + HttpUtility.UrlPathEncode(docnameBox.Text), "publishasname");
            }
            else
                pub = new Publish(app, this.CurrentDir, "publishas");
            pub.comments = commentBox.Text;
            pub.ShowDialog();
            if (pub.Publishsuccess == true && nameChanged != true)
            {
                SetWordDocumentProperties(app.ActiveDocument);
                app.ActiveDocument.Saved = false;
                app.ActiveDocument.Save();
            }
            this.ProgressBarThread.Abort();
            this.FillThread.Abort();
            Close();
        }

        private void PublishAs_Shown(object sender, EventArgs e)
        {
            if (moreInfo_developed == true)
            {
                Size s = new Size(620, 455);
                this.Size = s;
                this.Refresh();
            }
        }
    }
}
